home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / files / un.mount / un.mount.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  7.7 KB  |  361 lines

  1. /*
  2.     File:        Un/mount.c
  3.  
  4.     Contains:    This sample demonstrates how to handle disk-inserted events in a modal dialog.
  5.                 Along the way, it demonstrates how to field a disk-inserted event without allowing
  6.                 the system to automagically mount the volumes on the disk. (The code mounts the disk
  7.                 explicitly, but your program doesn't need to.)
  8.  
  9.     Written by: Pete Gontier
  10.  
  11.     Copyright:    Copyright © 1997-1999 by Apple Computer, Inc., All Rights Reserved.
  12.  
  13.                 You may incorporate this Apple sample source code into your program(s) without
  14.                 restriction. This Apple sample source code has been provided "AS IS" and the
  15.                 responsibility for its operation is yours. You are not permitted to redistribute
  16.                 this Apple sample source code as "Apple sample source code" after having made
  17.                 changes. If you're going to re-distribute the source, we require that you make
  18.                 it clear in the source that the code was descended from Apple sample source
  19.                 code, but that you've made changes.
  20.  
  21.     Change History (most recent first):
  22.                 7/1/1999    Karl Groethe         Updated for Metrowerks Codewarror Pro 2.1
  23.                 
  24.  
  25. */
  26. #define OLDROUTINELOCATIONS        0
  27. #define OLDROUTINENAMES            0
  28. #define SystemSevenOrLater        1
  29.  
  30. #ifndef __DISKS__
  31. #    include <Disks.h>
  32. #endif
  33.  
  34. #ifndef __DEVICES__
  35. #    include <Devices.h>
  36. #endif
  37.  
  38. #ifndef __FILES__
  39. #    include <Files.h>
  40. #endif
  41.  
  42. #ifndef __DISKINIT__
  43. #    include <DiskInit.h>
  44. #endif
  45.  
  46. #ifndef __FONTS__
  47. #    include <Fonts.h>
  48. #endif
  49.  
  50. #ifndef __DIALOGS__
  51. #    include <Dialogs.h>
  52. #endif
  53.  
  54.  
  55. #include <sound.h>
  56.  
  57. enum
  58. {
  59.     kResID_Dialog_MountUnmount = 128,
  60.     kResID_Dialog_Main
  61. };
  62.  
  63. enum
  64. {
  65.     kDialogItem_MountUnmount_None,
  66.     kDialogItem_MountUnmount_Button_Done,
  67.     kDialogItem_MountUnmount_StaticText_Waiting,
  68.     kDialogItem_MountUnmount_StaticText_VolName,
  69.     kDialogItem_MountUnmount_Button_Eject,
  70.     kDialogItem_MountUnmount_StaticText_HaveDisk
  71. };
  72.  
  73. static pascal OSErr InitMac (void)
  74. {
  75.     MaxApplZone ( );
  76.     InitGraf (&(qd.thePort));
  77.     InitFonts ( );
  78.     InitWindows ( );
  79.     InitMenus ( );
  80.     TEInit ( );
  81.     InitDialogs (nil);
  82.  
  83.     return noErr;
  84. }
  85.  
  86. static pascal void SetWatchCursor (void)
  87. {
  88.     SetCursor (*GetCursor (watchCursor));
  89. }
  90.  
  91. static pascal void ReconfigureInterfaceAfterMount (DialogRef dialog, Str27 volName)
  92. {
  93.     short    iType;
  94.     Handle    iHandle;
  95.     Rect    iRect;
  96.  
  97.     GetDialogItem (dialog,kDialogItem_MountUnmount_StaticText_VolName,
  98.         &iType, &iHandle, &iRect);
  99.     SetDialogItemText (iHandle,volName);
  100.  
  101.     GetDialogItem (dialog,kDialogItem_MountUnmount_Button_Eject,
  102.         &iType, &iHandle, &iRect);
  103.     HiliteControl ((ControlHandle) iHandle, 0);
  104.  
  105.     HideDialogItem (dialog,kDialogItem_MountUnmount_StaticText_Waiting);
  106.     ShowDialogItem (dialog,kDialogItem_MountUnmount_StaticText_HaveDisk);
  107. }
  108.  
  109. static pascal Boolean DriveIsFloppy (short driveNum)
  110. {
  111.     // this function isn't perfect but it isn't the purpose of this sample;
  112.     // a real program would qualify volumes much better
  113.  
  114.     return driveNum == 1 || driveNum == 2;
  115. }
  116.  
  117. static pascal OSErr AfterMount (OSErr mountErr, short driveNum, DialogRef dialog)
  118. {
  119.     OSErr err = noErr;
  120.  
  121.     // if mount failed, try to format and retry mount
  122.  
  123.     if (mountErr)
  124.     {
  125.         Point dibmWhere = { -1,-1 };
  126.         long fakeEventMessage = (((UInt32) mountErr) << 16) | driveNum;
  127.         err = DIBadMount (dibmWhere, fakeEventMessage);
  128.     }
  129.  
  130.     // regardless of whether we had to reformat the disk,
  131.     // if we successfully mounted it...
  132.  
  133.     if (!err && DriveIsFloppy (driveNum))
  134.     {
  135.         OSErr err2;
  136.  
  137.         // get the volume's name and poke it into the dialog
  138.  
  139.         Str27    volName;
  140.         short    vRefNum;
  141.         long    freeBytes;
  142.  
  143.         err = GetVInfo (driveNum, volName, &vRefNum, &freeBytes);
  144.  
  145.         if (err)
  146.         {
  147.             SysBeep (10);
  148.             SetWRefCon (dialog, 0);
  149.         }
  150.         else
  151.         {
  152.             ReconfigureInterfaceAfterMount (dialog,volName);
  153.             SetWRefCon (dialog, driveNum);
  154.         }
  155.  
  156.         // get rid of the newly-mounted volume (but don't eject its disk)
  157.  
  158.         err2 = UnmountVol (nil, driveNum);
  159.         if (!err2) err = err2;
  160.     }
  161.  
  162.     return err;
  163. }
  164.  
  165. static pascal Boolean GetNextEventModalFilterProc
  166.     (DialogRef dialog, EventRecord *event, short *itemHit)
  167. {
  168.     Boolean result = StdFilterProc (dialog,event,itemHit);
  169.  
  170.     if (event->what == nullEvent)
  171.     {
  172.         EventRecord diskInsertedEvent;
  173.  
  174.         // is there an unrequited disk-inserted event in the queue?
  175.  
  176.         if (OSEventAvail (diskMask, &diskInsertedEvent))
  177.         {
  178.             // it takes a while to mount a disk
  179.  
  180.             SetWatchCursor ( );
  181.  
  182.             // let the system mount the disk
  183.  
  184.             if (GetNextEvent (diskMask, &diskInsertedEvent))
  185.             {
  186.                 OSErr    err            = diskInsertedEvent.message >> 16;
  187.                 short    driveNum    = diskInsertedEvent.message;
  188.  
  189.                 err = AfterMount (err,driveNum,dialog);
  190.                 if (err) SysBeep (10);
  191.             }
  192.         }
  193.     }
  194.  
  195.     return result;
  196. }
  197.  
  198. static pascal Boolean GetOSEventModalFilterProc
  199.     (DialogRef dialog, EventRecord *event, short *itemHit)
  200. {
  201.     Boolean result = StdFilterProc (dialog,event,itemHit);
  202.  
  203.     if (event->what == nullEvent)
  204.     {
  205.         EventRecord diskInsertedEvent;
  206.  
  207.         // pull disk-inserted events from the queue before
  208.         // system mounts associated volume
  209.  
  210.         if (GetOSEvent (diskMask, &diskInsertedEvent))
  211.         {
  212.             ParamBlockRec    pbr;
  213.             short            driveNum = diskInsertedEvent.message;
  214.  
  215.             // mounting takes a while
  216.  
  217.             SetWatchCursor ( );
  218.  
  219.             // [attempt to mount the volume ourselves] and [react accordingly]
  220.  
  221.             pbr.volumeParam.ioVRefNum = driveNum;
  222.             if (AfterMount (PBMountVol (&pbr), driveNum, dialog))
  223.                 SysBeep (10);
  224.         }
  225.     }
  226.  
  227.     return result;
  228. }
  229.  
  230. static pascal void DisableEjectButton (DialogRef dlgRef)
  231. {
  232.     short    iType;
  233.     Handle    iHandle;
  234.     Rect    iRect;
  235.  
  236.     GetDialogItem (dlgRef,kDialogItem_MountUnmount_Button_Eject,
  237.         &iType,&iHandle,&iRect);
  238.     HiliteControl ((ControlHandle) iHandle, 255);
  239. }
  240.  
  241. static pascal void ReconfigureInterfaceAfterEject (DialogRef dlgRef)
  242. {
  243.     short    iType;
  244.     Handle    iHandle;
  245.     Rect    iRect;
  246.  
  247.     GetDialogItem (dlgRef,kDialogItem_MountUnmount_StaticText_VolName,
  248.         &iType, &iHandle, &iRect);
  249.     SetDialogItemText (iHandle,"\p");
  250.     ShowDialogItem (dlgRef,kDialogItem_MountUnmount_StaticText_Waiting);
  251.     HideDialogItem (dlgRef,kDialogItem_MountUnmount_StaticText_HaveDisk);
  252.     DisableEjectButton (dlgRef);
  253. }
  254.  
  255. static pascal OSErr EjectIfAny (DialogRef dlgRef)
  256. {
  257.     OSErr err = noErr;
  258.  
  259.     short driveNum = GetWRefCon (dlgRef);
  260.  
  261.     if (driveNum)
  262.     {
  263.         SetWatchCursor ( );
  264.  
  265.         if (!(err = Eject (nil, driveNum)))
  266.             SetWRefCon (dlgRef,0);
  267.     }
  268.  
  269.     return err;
  270. }
  271.  
  272.  
  273. static pascal void MountUnmount (ModalFilterProcPtr mfpp)
  274. {
  275.     ModalFilterUPP modalFilterUPP = NewModalFilterProc (mfpp);
  276.     if (modalFilterUPP)
  277.     {
  278.         DialogRef dlgRef = GetNewDialog (kResID_Dialog_MountUnmount,nil,(WindowRef)-1);
  279.         if (dlgRef)
  280.         {
  281.             short itemHit;
  282.  
  283.             SetDialogDefaultItem (dlgRef,ok);
  284.             SetDialogTracksCursor (dlgRef,true);
  285.             DisableEjectButton (dlgRef);
  286.             ShowWindow (dlgRef);
  287.  
  288.             do
  289.             {
  290.                 ModalDialog (modalFilterUPP,&itemHit);
  291.  
  292.                 if (itemHit == kDialogItem_MountUnmount_Button_Eject)
  293.                 {
  294.                     if (EjectIfAny (dlgRef))
  295.                         { SysBeep (10); break; }
  296.                     else
  297.                         ReconfigureInterfaceAfterEject (dlgRef);
  298.                 }
  299.             }
  300.             while (kDialogItem_MountUnmount_Button_Done != itemHit);
  301.  
  302.             if (EjectIfAny (dlgRef)) SysBeep (10);
  303.             DisposeDialog (dlgRef);
  304.         }
  305.  
  306.         DisposeRoutineDescriptor (modalFilterUPP);
  307.     }
  308. }
  309.  
  310. void main (void)
  311. {
  312.     if (InitMac ( ))
  313.         SysBeep (10);
  314.     else
  315.     {
  316.         DialogRef dlgRef = GetNewDialog (kResID_Dialog_Main,nil,(WindowRef)-1);
  317.         if (dlgRef)
  318.         {
  319.             ModalFilterUPP modalFilterUPP;
  320.  
  321.             if (GetStdFilterProc (&modalFilterUPP))
  322.                 SysBeep (10);
  323.             else
  324.             {
  325.                 enum
  326.                 {
  327.                     kDialogItem_None,
  328.                     kDialogItem_Button_Quit,
  329.                     kDialogItem_Button_GetNextEvent,
  330.                     kDialogItem_Button_GetOSEvent
  331.                 };
  332.  
  333.                 short itemHit;
  334.  
  335.                 SetDialogDefaultItem (dlgRef,kDialogItem_Button_Quit);
  336.                 SetDialogTracksCursor (dlgRef,true);
  337.  
  338.                 do
  339.                 {
  340.                     ModalDialog (modalFilterUPP,&itemHit);
  341.  
  342.                     switch (itemHit)
  343.                     {
  344.                         case kDialogItem_Button_GetNextEvent    :
  345.  
  346.                             MountUnmount (GetNextEventModalFilterProc);
  347.                             break;
  348.  
  349.                         case kDialogItem_Button_GetOSEvent        :
  350.  
  351.                             MountUnmount (GetOSEventModalFilterProc);
  352.                             break;
  353.                     }
  354.                 }
  355.                 while (itemHit != kDialogItem_Button_Quit);
  356.             }
  357.             DisposeDialog (dlgRef);
  358.         }
  359.     }
  360. }
  361.